package enemies 
{
	import entities.Entity;
	/**
	 * ...
	 * @author Gareth Williams
	 */
	public class SinePath implements IStrategyImplementation 
	{
		public var frequency:Number;
		public var amplitude:Number;
		
		private var timestepAtInstantiation:int;
		private var isInitialised:Boolean = false;
		private var initialised:Boolean = false;
		private var yOffset:Number = 0;
		
		public function SinePath(frequency:Number, amplitude:Number) 
		{
			this.frequency = frequency;
			this.amplitude = amplitude;
			
			timestepAtInstantiation = Main.timestep;
		}
		
		/* INTERFACE enemies.IStrategyImplementation */
		
		public function perform(on:Entity):Boolean 
		{
			if (!isInitialised)
			{
				yOffset = on.y;
				isInitialised = true;
			}
			
			//get projected x position for timestep
			var tDelta:Number 		= Main.timestep - timestepAtInstantiation;
			var projectedX:Number 	= tDelta * on.speed;
			var projectedY:Number 	= yOffset;
			
			//get phase for timestep
			var phase:Number 	= (1/Constants.SCREEN_WIDTH) * tDelta;
			//var sine:Number 	= Math.sin(phase * frequency * Constants.TWO_PI);
			
			var x:Number = phase * frequency * Constants.TWO_PI;
			var sine:Number = 0;
			
			//http://lab.polygonal.de/2007/07/18/fast-and-accurate-sinecosine-approximation/
			
			//performance gain is lost with function call
			//always wrap input angle to -PI..PI
			if (x < -3.14159265)
				x += 6.28318531;
			else
			if (x >  3.14159265)
				x -= 6.28318531;

			//compute sine
			if (x < 0)
				sine = 1.27323954 * x + .405284735 * x * x;
			else
				sine = 1.27323954 * x - 0.405284735 * x * x;

			//----------------------------------------------------------------------------------
			
			on.x = projectedX;
			on.y = projectedY + sine * amplitude;
			
			var isOutOfBounds:Boolean = false;
			if (on.x > Constants.SCREEN_WIDTH) isOutOfBounds = true;
			if (on.x < 0) isOutOfBounds = true;
			if (on.y > Constants.SCREEN_HEIGHT) isOutOfBounds = true;
			if (on.y < 0) isOutOfBounds = true;
			
			return isOutOfBounds;
		}
	}
}